/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package findAntlrRules;

import antlrGrammar.ANTLRv3Lexer;
import antlrGrammar.ANTLRv3Parser;
import java.io.File;
import java.util.ArrayList;
import org.antlr.runtime.ANTLRFileStream;
import org.antlr.runtime.TokenRewriteStream;
import org.antlr.runtime.tree.CommonTree;

/**
 * Parse the input grammar and find all language rules
 * @author daniel
 */
public class FindAntlrRules {

    public static ArrayList<AntlrRule> orderedRuleList = new ArrayList<AntlrRule>();
    public static ArrayList<AntlrRule> tokenList = new ArrayList<AntlrRule>();
    /**
     * Construct ordered grammar rule list 
     * @param file grammar file
     * @throws Exception 
     */
    public static void getOrderedRules(String file) throws Exception {
        try {
        	ANTLRv3Parser.rules.clear();
        	tokenList.clear();
        	ANTLRv3Parser.rule=new AntlrRule();
            AntlrRule.setGrammarFile(file);
            orderedRuleList.clear();
            ANTLRFileStream fs = new ANTLRFileStream(file);
            ANTLRv3Lexer lex = new ANTLRv3Lexer(fs);

            TokenRewriteStream tokens = new TokenRewriteStream(lex);

            ANTLRv3Parser p = new ANTLRv3Parser(tokens);
            p.grammarDef();
            // rule out all token declaration 
            // in antlr grammar a token declaration is identified by the fact that rule name is in uppercase
            for (int i = 0 ; i<ANTLRv3Parser.rules.size(); i++ ){
                if (ANTLRv3Parser.rules.get(i).getName().toUpperCase().trim().equals(ANTLRv3Parser.rules.get(i).getName().trim())){
                	tokenList.add(ANTLRv3Parser.rules.get(i));
                	ANTLRv3Parser.rules.remove(i);
                    i--;
                }
            }
            /*
            orderedRuleList = ANTLRv3Parser.rules;
            boolean ok = true ; 
            for (int i = 0 ; i < orderedRuleList.size() && ok ; i++){
            	ok = false;
            	for (int j = 0 ; j < orderedRuleList.size() ; j++){
            		if (j !=i){
            			if((orderedRuleList.get(i).getName().trim().equals("stmts")&& orderedRuleList.get(j).getName().trim().equals("pgm") ) ||
            					(orderedRuleList.get(j).getName().trim().equals("stmts")&& orderedRuleList.get(i).getName().trim().equals("pgm") )	){
            				int k =0 ;
            				k++;
            			}
            			if (orderedRuleList.get(i).compare(orderedRuleList.get(j)) == -1 ){
            				ok = true;
            				AntlrRule aux = orderedRuleList.get(i);
            				orderedRuleList.remove(i);
            				orderedRuleList.add(i, orderedRuleList.get(i>j?j:j-1));
            				orderedRuleList.remove(j);
            				orderedRuleList.add(j, aux);
            			}
            		}
            	}
            }*/
            orderedRuleList.add(ANTLRv3Parser.rules.get(0));
            // order rules 
            for (int i = 0; i < ANTLRv3Parser.rules.size(); i++) {
                for (int j = 0; j < ANTLRv3Parser.rules.size(); j++) {
                    if (!ANTLRv3Parser.rules.get(i).equals(ANTLRv3Parser.rules.get(j))) {
                        int i2 = orderedRuleList.indexOf(ANTLRv3Parser.rules.get(j));
                        int i1 = orderedRuleList.indexOf(ANTLRv3Parser.rules.get(i));
                        if (ANTLRv3Parser.rules.get(i).getList().contains(ANTLRv3Parser.rules.get(j).getName()) && (i1 > i2) && (i1 > -1) && (i2 > -1)) {
                            orderedRuleList.remove(i1);
                            orderedRuleList.add(i2, ANTLRv3Parser.rules.get(i));
                        } else if (!orderedRuleList.contains(ANTLRv3Parser.rules.get(j))) {
                            orderedRuleList.add(ANTLRv3Parser.rules.get(j));
                        }

                    }

                }
            }
            for (int i = 0; i < orderedRuleList.size(); i++) {
                System.out.println(orderedRuleList.get(i));
            }
        } catch (Exception e) {
            e.printStackTrace();
            orderedRuleList.clear();
            throw e;
        }
    }

}
